#include <stdio.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "esp_http_server.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include <ctype.h>

// 定义标签和常量
#define TAG "wifi_prov"
#define PROV_SSID "ESP32-Config"
#define PROV_PASS ""
#define CAPTIVE_PORTAL_TASK_PRIORITY 5
#define CAPTIVE_PORTAL_TASK_STACK_SIZE 4096

// 全局变量
static char wifi_ssid[32] = {0};
static char wifi_pass[64] = {0};
static httpd_handle_t server = NULL;
static TaskHandle_t captive_portal_task_handle = NULL;

// HTML配置页面
static const char* CONFIG_HTML = 
"<html><head><meta charset='UTF-8'><title>ESP32 WiFi配置</title><meta name='viewport' content='width=device-width, initial-scale=1'>"
"<style>body{font-family:Arial;background:#f0f0f0;margin:40px}form{background:#fff;padding:20px;border-radius:5px;box-shadow:0 2px 10px rgba(0,0,0,.1)}"
"input[type=text],input[type=password]{width:100%;padding:10px;margin:8px 0;border:1px solid #ccc;border-radius:4px;box-sizing:border-box}"
"input[type=submit]{background:#4CAF50;color:#fff;padding:12px;border:none;border-radius:4px;cursor:pointer;width:100%}"
"input[type=submit]:hover{background:#45a049}</style></head>"
"<body><h2>ESP32 WiFi配置</h2><form method='post' action='/configure'>"
"<label>WiFi名称 (SSID):</label><input type='text' name='ssid' required>"
"<label>WiFi密码:</label><input type='password' name='password'>"
"<input type='submit' value='配置'></form></body></html>";

// 配置成功页面
static const char* SUCCESS_HTML = 
"<html><head><meta charset='UTF-8'><title>配置成功</title><meta http-equiv='refresh' content='5;url=/'>"
"<style>body{font-family:Arial;background:#f0f0f0;text-align:center;margin:40px}"
"div{background:#fff;padding:20px;border-radius:5px;box-shadow:0 2px 10px rgba(0,0,0,.1)}</style>"
"</head><body><div><h2>配置成功!</h2><p>ESP32正在尝试连接WiFi，请稍候...</p></div></body></html>";

// URL解码函数
static void url_decode(const char *src, char *dst, size_t dst_size) {
    char a, b;
    size_t i = 0;
    while (*src && i < dst_size - 1) {
        if (*src == '%') {
            if ((a = src[1]) && (b = src[2]) && isxdigit(a) && isxdigit(b)) {
                if (a >= 'a') a -= 'a' - 'A';
                if (a >= 'A') a -= 'A' - 10;
                else a -= '0';
                if (b >= 'a') b -= 'a' - 'A';
                if (b >= 'A') b -= 'A' - 10;
                else b -= '0';
                *dst++ = 16 * a + b;
                src += 3;
                i++;
                continue;
            }
        } else if (*src == '+') {
            *dst++ = ' ';
            src++;
            i++;
            continue;
        }
        *dst++ = *src++;
        i++;
    }
    *dst = '\0';
}

// 根URL处理器
static esp_err_t root_get_handler(httpd_req_t *req) {
    return httpd_resp_send(req, CONFIG_HTML, HTTPD_RESP_USE_STRLEN);
}

// 通配符处理器 - 捕获所有请求并重定向到配置页面
static esp_err_t captive_portal_handler(httpd_req_t *req) {
    // 如果请求的不是根路径，重定向到根路径
    if (strcmp(req->uri, "/") != 0 && strcmp(req->uri, "/configure") != 0) {
        httpd_resp_set_status(req, "302 Found");
        httpd_resp_set_hdr(req, "Location", "http://192.168.4.1/");
        return httpd_resp_send(req, NULL, 0);
    }
    
    // 如果是根路径，返回配置页面
    return root_get_handler(req);
}

// 配置提交处理器
static esp_err_t configure_post_handler(httpd_req_t *req) {
    char buf[100];
    int ret = httpd_req_recv(req, buf, sizeof(buf)-1);
    if (ret <= 0) return ESP_FAIL;
    buf[ret] = 0;
    
    // 解析表单数据
    char *ssid_start = strstr(buf, "ssid=");
    char *pass_start = strstr(buf, "password=");
    
    if (ssid_start) {
        ssid_start += 5;
        char *ssid_end = strchr(ssid_start, '&');
        if (ssid_end) *ssid_end = 0;
        url_decode(ssid_start, wifi_ssid, sizeof(wifi_ssid));
    }
    
    if (pass_start) {
        pass_start += 9;
        url_decode(pass_start, wifi_pass, sizeof(wifi_pass));
    }
    
    ESP_LOGI(TAG, "收到配置: SSID=%s, Password=%s", wifi_ssid, wifi_pass);
    httpd_resp_send(req, SUCCESS_HTML, HTTPD_RESP_USE_STRLEN);
    
    // 停止HTTP服务器和Captive Portal任务
    if (server) {
        httpd_stop(server);
        server = NULL;
    }
    
    if (captive_portal_task_handle) {
        vTaskDelete(captive_portal_task_handle);
        captive_portal_task_handle = NULL;
    }
    
    // 保存WiFi配置到NVS
    nvs_handle_t nvs;
    if (nvs_open("wifi_config", NVS_READWRITE, &nvs) == ESP_OK) {
        nvs_set_str(nvs, "ssid", wifi_ssid);
        nvs_set_str(nvs, "password", wifi_pass);
        nvs_commit(nvs);
        nvs_close(nvs);
    }
    
    // 切换到STA模式并连接WiFi
    esp_wifi_disconnect();
    esp_wifi_stop();
    
    wifi_config_t wifi_config = {0};
    strncpy((char*)wifi_config.sta.ssid, wifi_ssid, sizeof(wifi_config.sta.ssid));
    strncpy((char*)wifi_config.sta.password, wifi_pass, sizeof(wifi_config.sta.password));
    
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
    esp_wifi_connect();
    
    return ESP_OK;
}

// URI处理器定义
static const httpd_uri_t root = {
    .uri = "/",
    .method = HTTP_GET,
    .handler = root_get_handler
};

static const httpd_uri_t configure = {
    .uri = "/configure",
    .method = HTTP_POST,
    .handler = configure_post_handler
};

static const httpd_uri_t captive = {
    .uri = "/*",
    .method = HTTP_GET,
    .handler = captive_portal_handler
};

// 启动HTTP服务器
static void start_webserver(void) {
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = 80;
    config.uri_match_fn = httpd_uri_match_wildcard;
    
    if (httpd_start(&server, &config) == ESP_OK) {
        httpd_register_uri_handler(server, &root);
        httpd_register_uri_handler(server, &configure);
        httpd_register_uri_handler(server, &captive);
        ESP_LOGI(TAG, "HTTP服务器启动成功");
    }
}

// DNS服务器任务 - 拦截所有DNS请求并指向本机
static void dns_server_task(void *pvParameters) {
    struct sockaddr_in dest_addr;
    dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(53);
    
    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock < 0) {
        ESP_LOGE(TAG, "无法创建DNS套接字");
        vTaskDelete(NULL);
        return;
    }
    
    if (bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
        ESP_LOGE(TAG, "无法绑定DNS套接字");
        close(sock);
        vTaskDelete(NULL);
        return;
    }
    
    ESP_LOGI(TAG, "DNS服务器已启动");
    
    while (1) {
        struct sockaddr_in source_addr;
        socklen_t addr_len = sizeof(source_addr);
        char buf[512];
        int len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&source_addr, &addr_len);
        
        if (len > 0) {
            // 简单DNS响应 - 将所有查询指向192.168.4.1
            char response[512];
            memset(response, 0, sizeof(response));
            
            // 复制请求头
            memcpy(response, buf, len);
            
            // 设置响应标志
            response[2] = 0x81; // 标准查询响应
            response[3] = 0x80; // 无错误
            
            // 设置回答计数为1
            response[6] = 0x00;
            response[7] = 0x01;
            
            // 填充回答部分
            int pos = len;
            response[pos++] = 0xC0; // 指针到查询域名
            response[pos++] = 0x0C;
            
            response[pos++] = 0x00; // 类型A
            response[pos++] = 0x01;
            
            response[pos++] = 0x00; // 类IN
            response[pos++] = 0x01;
            
            response[pos++] = 0x00; // TTL 300秒
            response[pos++] = 0x00;
            response[pos++] = 0x01;
            response[pos++] = 0x2C;
            
            response[pos++] = 0x00; // 数据长度4字节
            response[pos++] = 0x04;
            
            response[pos++] = 192; // IP地址192.168.4.1
            response[pos++] = 168;
            response[pos++] = 4;
            response[pos++] = 1;
            
            sendto(sock, response, pos, 0, (struct sockaddr *)&source_addr, addr_len);
        }
        
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }
}

// WiFi事件处理器
static void wifi_event_handler(void* arg, esp_event_base_t event_base, 
                              int32_t event_id, void* event_data) {
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        ESP_LOGI(TAG, "连接断开，尝试重新连接...");
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "获取到IP地址: " IPSTR, IP2STR(&event->ip_info.ip));
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_START) {
        // AP启动后启动DNS服务器
        xTaskCreate(dns_server_task, "dns_server", 4096, NULL, CAPTIVE_PORTAL_TASK_PRIORITY, &captive_portal_task_handle);
    }
}

// 启动配置AP
static void start_provisioning_ap(void) {
    ESP_LOGI(TAG, "启动配置AP");
    
    wifi_config_t ap_config = {
        .ap = {
            .ssid = PROV_SSID,
            .ssid_len = strlen(PROV_SSID),
            .channel = 1,
            .password = PROV_PASS,
            .max_connection = 4,
            .authmode = strlen(PROV_PASS) ? WIFI_AUTH_WPA_WPA2_PSK : WIFI_AUTH_OPEN,
        },
    };
    
    esp_wifi_set_mode(WIFI_MODE_AP);
    esp_wifi_set_config(WIFI_IF_AP, &ap_config);
    esp_wifi_start();
    
    ESP_LOGI(TAG, "配置AP已启动: %s", PROV_SSID);
    start_webserver();
}

// 应用程序主函数
void app_main(void) {
    // 初始化NVS
    ESP_ERROR_CHECK(nvs_flash_init());
    
    // 初始化网络
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_ap();
    esp_netif_create_default_wifi_sta();
    
    // 初始化WiFi
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    
    // 注册事件处理器
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));
    
    // 从NVS加载保存的WiFi配置
    nvs_handle_t nvs;
    if (nvs_open("wifi_config", NVS_READONLY, &nvs) == ESP_OK) {
        size_t ssid_len = sizeof(wifi_ssid);
        size_t pass_len = sizeof(wifi_pass);
        if (nvs_get_str(nvs, "ssid", wifi_ssid, &ssid_len) == ESP_OK &&
            nvs_get_str(nvs, "password", wifi_pass, &pass_len) == ESP_OK) {
            ESP_LOGI(TAG, "发现保存的WiFi配置: %s", wifi_ssid);
            
            // 尝试连接到保存的WiFi
            wifi_config_t wifi_config = {0};
            strncpy((char*)wifi_config.sta.ssid, wifi_ssid, sizeof(wifi_config.sta.ssid));
            strncpy((char*)wifi_config.sta.password, wifi_pass, sizeof(wifi_config.sta.password));
            
            esp_wifi_set_mode(WIFI_MODE_STA);
            esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
            esp_wifi_start();
            esp_wifi_connect();
            
            nvs_close(nvs);
            return;
        }
        nvs_close(nvs);
    }
    
    // 没有保存的配置，启动配置模式
    start_provisioning_ap();
}